package com.basics.common.utils;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

public class Object2SortedMappUtil {

	/**
	 * 将POJO对象转换成SortMap排序集合（按照属性的字典排序）
	 *
	 * @param obj
	 * @return
	 */
	public static SortedMap<Object, Object> getSortedMapObj(Object obj) {

		List<String> fieldNames = new ArrayList<String>();

		SortedMap<Object, Object> sortedMap = new TreeMap<Object, Object>();

		fieldNames = getFieldName(obj);

		for (int i = 0; i < fieldNames.size(); i++) {

			if (!"serialVersionUID".equals(fieldNames.get(i))) {
				sortedMap.put(fieldNames.get(i), String.valueOf(getFieldValueByName(fieldNames.get(i), obj)));
			}

		}

		return sortedMap;

	}

	public static SortedMap<String, String> getSortedMapStr(Object obj) {

		List<String> fieldNames = new ArrayList<String>();

		SortedMap<String, String> sortedMap = new TreeMap<String, String>();

		fieldNames = getFieldName(obj);

		for (int i = 0; i < fieldNames.size(); i++) {

			if (!"serialVersionUID".equals(fieldNames.get(i))) {
				sortedMap.put(fieldNames.get(i), (String) getFieldValueByName(fieldNames.get(i), obj));
			}
		}

		return sortedMap;
	}

	/**
	 * 根据属性名获取属性值
	 *
	 * @param fieldName
	 *            ：属性名
	 * @param obj
	 *            ：POJO对象
	 * @return
	 */
	private static Object getFieldValueByName(String fieldName, Object obj) {

		try {

			String firstLetter = fieldName.substring(0, 1).toUpperCase();

			String getter = "get" + firstLetter + fieldName.substring(1);

			Method method = obj.getClass().getMethod(getter, new Class[] {});

			Object value = method.invoke(obj, new Object[] {});

			return value;

		} catch (Exception e) {

			System.out.println(e);

			return null;

		}

	}

	/**
	 * 获取属性名数组
	 *
	 * @param obj
	 *            ：POJO对象
	 * @return
	 */
	private static List<String> getFieldName(Object obj) {

		Field[] fields = obj.getClass().getDeclaredFields();

		List<String> fieldNames = new ArrayList<String>();

		for (int i = 0; i < fields.length; i++) {

			fieldNames.add(fields[i].getName());

		}

		return fieldNames;

	}

	/**
	 * 将一个 Map 对象转化为一个 JavaBean
	 *
	 * @param type
	 *            要转化的类型
	 * @param map
	 *            包含属性值的 map
	 * @return 转化出来的 JavaBean 对象
	 * @throws IntrospectionException
	 *             如果分析类属性失败
	 * @throws IllegalAccessException
	 *             如果实例化 JavaBean 失败
	 * @throws InstantiationException
	 *             如果实例化 JavaBean 失败
	 * @throws InvocationTargetException
	 *             如果调用属性的 setter 方法失败
	 */
	@SuppressWarnings("rawtypes")
	public static Object convertMap(Class type, Map map) throws IntrospectionException, IllegalAccessException, InstantiationException, InvocationTargetException {
		BeanInfo beanInfo = Introspector.getBeanInfo(type); // 获取类属性
		Object obj = type.newInstance(); // 创建 JavaBean 对象
		// 给 JavaBean 对象的属性赋值
		PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
		for (int i = 0; i < propertyDescriptors.length; i++) {
			PropertyDescriptor descriptor = propertyDescriptors[i];
			String propertyName = descriptor.getName();
			if (map.containsKey(propertyName)) {
				// 下面一句可以 try 起来，这样当一个属性赋值失败的时候就不会影响其他属性赋值。
				Object value = map.get(propertyName);
				Object[] args = new Object[1];
				args[0] = value;
				descriptor.getWriteMethod().invoke(obj, args);
			}
		}
		return obj;
	}
}
